package com.ethink.warehouse.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ethink.framework.common.db.PageUtils;
import com.ethink.framework.common.exception.BusinessException;
import com.ethink.warehouse.api.constant.WarehouseRespCode;
import com.ethink.warehouse.api.info.WarehouseInfo;
import com.ethink.warehouse.api.request.*;
import com.ethink.warehouse.api.response.WarehouseAddResponse;
import com.ethink.warehouse.api.response.WarehouseDetailsResponse;
import com.ethink.warehouse.common.entity.Warehouse;
import com.ethink.warehouse.common.entity.WarehouseBook;
import com.ethink.warehouse.common.mapper.WarehouseBookMapper;
import com.ethink.warehouse.common.mapper.WarehouseMapper;
import com.ethink.warehouse.converter.WarehouseConverter;
import com.ethink.warehouse.service.WarehouseService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 仓库主仓 Service接口实现
 *
 * @author default
 * @date 2022-11-01
 */
@Slf4j
@Service
public class WarehouseServiceImpl implements WarehouseService {

    @Autowired
    private WarehouseMapper warehouseMapper;

    @Autowired
    private WarehouseBookMapper warehouseBookMapper;

    @Autowired
    private WarehouseConverter warehouseConverter;

    @Override
    public Page<WarehouseInfo> queryWarehouse(WarehouseQueryRequest request) {
        return warehouseMapper.queryWarehouse(PageUtils.buildPage(request), request);
    }

    @Override
    public WarehouseDetailsResponse getWarehouseById(Long warehouseId) {
        WarehouseDetailsResponse response = new WarehouseDetailsResponse();
        // 主仓详情
        response.setWarehouseInfo(warehouseMapper.getWarehouseById(warehouseId));
        // 主仓账册列表
        response.setWarehouseBookInfoList(warehouseBookMapper.getWarehouseBookByWarehouseId(warehouseId));
        return response;
    }

    @Override
    public List<WarehouseInfo> listWarehouse() {
        return warehouseMapper.listWarehouse();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public WarehouseAddResponse addWarehouse(WarehouseAddRequest request) {
        LambdaQueryWrapper<Warehouse> warehouseQueryWrapper = new LambdaQueryWrapper<>();
        warehouseQueryWrapper.eq(Warehouse::getWarehouseCode, request.getWarehouseCode());
        warehouseQueryWrapper.eq(Warehouse::getIsDeleted, false);
        Integer existedWarehouseCount = warehouseMapper.selectCount(warehouseQueryWrapper);
        if (existedWarehouseCount > 0) {
            throw new BusinessException(WarehouseRespCode.WAREHOUSE_ADD_WAREHOUSE_CODE_EXISTED_ERR);
        }

        WarehouseAddResponse response = new WarehouseAddResponse();
        Warehouse warehouse = new Warehouse();
        BeanUtils.copyProperties(request, warehouse);
        warehouseMapper.insert(warehouse);
        // 保存主仓账册
        for (WarehouseAddBookRequest warehouseAddBookRequest : request.getWarehouseBookList()) {
            WarehouseBook warehouseBook = new WarehouseBook();
            BeanUtils.copyProperties(warehouseAddBookRequest, warehouseBook);
            warehouseBook.setWarehouseId(warehouse.getId());
            warehouseBook.setBookGroup(warehouseAddBookRequest.getBookCode());
            warehouseBookMapper.insert(warehouseBook);
        }
        response.setId(warehouse.getId());
        return response;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateWarehouse(WarehouseUpdateRequest request) {
        LambdaUpdateWrapper<Warehouse> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Warehouse::getId, request.getId());
        updateWrapper.set(Warehouse::getWarehouseName, request.getWarehouseName());
        updateWrapper.set(Warehouse::getWarehouseStatus, request.getWarehouseStatus());
        updateWrapper.set(Warehouse::getBizType, request.getBizType());
        updateWrapper.set(Warehouse::getIsOutbound, request.getIsOutbound());
        updateWrapper.set(Warehouse::getIsVirtual, request.getIsVirtual());
        updateWrapper.set(Warehouse::getCountryCode, request.getCountryCode());
        updateWrapper.set(Warehouse::getProvinceCode, request.getProvinceCode());
        updateWrapper.set(Warehouse::getCityCode, request.getCityCode());
        updateWrapper.set(Warehouse::getAreaCode, request.getAreaCode());
        updateWrapper.set(Warehouse::getFullAddress, request.getFullAddress());
        updateWrapper.set(Warehouse::getAddress, request.getAddress());
        updateWrapper.set(Warehouse::getContactsName, request.getContactsName());
        updateWrapper.set(Warehouse::getContactsPhone, request.getContactsPhone());
        updateWrapper.set(Warehouse::getRemark, request.getRemark());
        warehouseMapper.update(null, updateWrapper);

        Map<String, WarehouseUpdateBookRequest> warehouseUpdateBookRequestMap = request.getWarehouseBookList()
                .stream().collect(Collectors.toMap(WarehouseUpdateBookRequest::getBookCode, req -> req));

        LambdaQueryWrapper<WarehouseBook> warehouseBookQueryWrapper = new LambdaQueryWrapper<>();
        warehouseBookQueryWrapper.eq(WarehouseBook::getWarehouseId, request.getId());
        List<WarehouseBook> warehouseBooks = warehouseBookMapper.selectList(warehouseBookQueryWrapper);
        List<String> existBookCodeList = new ArrayList<>();
        List<Long> deleteBookIdList = new ArrayList<>();
        for (WarehouseBook warehouseBook : warehouseBooks) {
            WarehouseUpdateBookRequest bookRequest = warehouseUpdateBookRequestMap.get(warehouseBook.getBookCode());
            if (bookRequest != null) {
                LambdaUpdateWrapper<WarehouseBook> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
                lambdaUpdateWrapper
                        .set(WarehouseBook::getOwnerCode, warehouseBook.getOwnerCode())
                        .eq(WarehouseBook::getId, warehouseBook.getId());
                warehouseBookMapper.update(null, lambdaUpdateWrapper);
                existBookCodeList.add(warehouseBook.getBookCode());
            } else {
                deleteBookIdList.add(warehouseBook.getId());
            }
        }
        for (WarehouseUpdateBookRequest bookRequest : request.getWarehouseBookList()) {
            if (!existBookCodeList.contains(bookRequest.getBookCode())) {
                // 新增
                WarehouseBook newWarehouseBook = new WarehouseBook();
                BeanUtils.copyProperties(bookRequest, newWarehouseBook);
                newWarehouseBook.setBookGroup(bookRequest.getBookCode());
                newWarehouseBook.setWarehouseId(request.getId());
                warehouseBookMapper.insert(newWarehouseBook);
            }
        }
        if (CollectionUtils.isNotEmpty(deleteBookIdList)) {
            // TODO 删除时需要判断是否被分仓使用或在物流跟进单中有关联数据
            warehouseBookMapper.deleteBatchIds(deleteBookIdList);
        }
    }

    @Override
    public void setWarehouseStatus(WarehouseStatusSetRequest request) {
        LambdaUpdateWrapper<Warehouse> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Warehouse::getId, request.getId());
        updateWrapper.set(Warehouse::getWarehouseStatus, request.getWarehouseStatus());
        warehouseMapper.update(null, updateWrapper);
    }

}